package chemistry;

import java.util.ArrayList;
import java.util.Collections;


public class FormulaParser{
	
	public static boolean isNumber(String s){
		for (int i=0; i < s.length(); i++){
			if (!Character.isDigit(s.charAt(i))){
				return false;
			}
		}
		return true;
	}
	
	public static ArrayList<String> getTokens(String s){
		String currentToken = "";
		ArrayList<String> tokens = new ArrayList<String>();
		boolean parens = false;
		boolean endParen = false;
		s += (char)0;
		for (int i = 0; i < s.length(); i++){
			char c = s.charAt(i);
			if (c == '('){
					tokens.add(currentToken);
					currentToken = "(";
					parens = true;
			} else if (parens) {
				if (c == ')'){
					parens = false;
					endParen = true;
				} else {
					currentToken += c;
				}
			} else if (Character.isUpperCase(c)){
				tokens.add(currentToken);
				currentToken = "" + c;
			} else if (Character.isDigit(c)){
				if (endParen){
					tokens.add(currentToken = ")");
					endParen = false;
					currentToken = "";
				} else if (currentToken.length() > 0 &&
						   Character.isDigit(currentToken.charAt(currentToken.length() - 1))){
					currentToken += c;
				} else {
					tokens.add(currentToken);
					currentToken = "" + c;
				}
			} else if ((int) c ==  0) {
				tokens.add(currentToken);
			} else {
				currentToken += c;
			}
		}
		tokens.remove(0);
		return tokens;
	}
	
	public static ArrayList<String> parse(String s){
		ArrayList<String> tokens = getTokens(s);
		String lastToken = "";
		ArrayList<String> atoms = new ArrayList<String>();
		for (String t:tokens){
			if (isNumber(t)){
				for (int i=0; i < Integer.parseInt(t); i++){
					atoms.add(lastToken);
				}
			} else {
				if (!isNumber(lastToken)){
					atoms.add(lastToken);
				}
				lastToken = t;
			}
		}
		atoms.add(lastToken);
		return atoms;
	}
	
	@SuppressWarnings("unchecked")
	public static ArrayList<Element> getElements(String s, ElementList e){
		ArrayList<String> atoms = parse(s);
		ArrayList<Element> elements = new ArrayList<Element>();
		for (String str:atoms){
			elements.add(e.getElement(str));
		}
		Collections.sort(elements);
		return elements;
	}
	
	public static String deparse(ArrayList<Element> elements, ElementList list){
//		String str = "";
//		for (Element e:elements){
//			str += e.getSymbol();
//		}
//		return str;
		ArrayList<String> symbols = new ArrayList<String>();
		ArrayList<Integer> counts = new ArrayList<Integer>();
		for (Element e:elements){
			String s = e.getSymbol();
			if (symbols.contains(s)){
				int ind = symbols.indexOf(s);
				counts.set(ind, counts.get(ind) + 1);
			} else if (list.isNonMetal(e)){
				symbols.add(s);
				counts.add(1);
			} else {
				symbols.add(0, s);
				counts.add(0, 1);
			}
		}
		String formula = "";
		for (int i = 0; i < symbols.size(); i++){
			formula += symbols.get(i);
			int count = counts.get(i);
			if (count > 1){
				formula += count;
			}
		}
		return formula;
	}
	
	public static double getMass(ArrayList<Element> elements){
		double mass = 0;
		for (Element e: elements){
			mass += e.getMass();
		}
		return mass;
	}
}
